package com.sc.handler;

import lombok.extern.slf4j.Slf4j;
import org.json.JSONObject;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.cloud.gateway.support.NotFoundException;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ResponseStatusException;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 捕获spring cloud gateway和webflux异常，实现处理web请求异常的接口
 */
@Order(-1)   //指定异常处理器的优先级，数值越小，优先级越高，此处高于框架默认的异常处理器（DefaultErrorWebExceptionHandler）
@Configuration
@Slf4j
public class GatewayExceptionHandler implements ErrorWebExceptionHandler {

    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable ex) {
        //获取响应实例
        ServerHttpResponse httpResponse = exchange.getResponse();
        //判断响应结果是否已经被提交，如果被提交，表示已经响应，无需再进行异常处理
        if (httpResponse.isCommitted()){
            return Mono.error(ex);
        }
        //如果响应没有被提交，将异常信息写入响应中（返回具体的响应类型，需要进行判断）
        String msg;
        if (ex instanceof NotFoundException){
            msg = "找不到服务";
        }else if(ex instanceof ResponseStatusException){
            msg = ((ResponseStatusException) ex).getMessage();
        }else {
            msg = "内部服务器错误";
        }
        //服务器打印错误日志
        log.error("网关服务异常，请求路径：{"+exchange.getRequest().getPath()+"}, 错误信息：{"+ex.getMessage()+"}");

        return httpResponse.writeWith(Mono.just(error(httpResponse,msg)));
    }
    DataBuffer error(ServerHttpResponse response, String msg){
        //设置响应的格式和编码
        response.getHeaders().add("Content-Type","application/json;charset=utf-8");

        //设置响应状态码()
        response.setStatusCode(HttpStatus.INTERNAL_SERVER_ERROR);
        //将错误信息封装为json格式，写入响应
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code",0);
        jsonObject.put("msg",msg);

        return response.bufferFactory().wrap(jsonObject.toString().getBytes());
    }
}
